#include "ET++.ph"
#include "PrintManager.h"

#include "Class.h"
#include "String.h"
#include "Scroller.h"
#include "Box.h"
#include "Window.h"
#include "WindowPort.h"
#include "WindowSystem.h"
#include "PrintPort.h"
#include "BorderItems.h"
#include "Buttons.h"
#include "Printer.h"
#include "PictPort.h"
#include "Picture.h"
#include "PictureItem.h"

extern void DrawShadow(const Rectangle &r, const Point &delta, Ink* fg, Ink *bg);

//---- PreviewPageItem ---------------------------------------------------------

class PreviewPageItem : public PictureItem {
public:
	MetaDef(PreviewPageItem);
	PreviewPageItem() : PictureItem((Picture*)0)
		{ }
	void SetPicture(Picture *bm, bool redraw= TRUE);
	Metric GetMinSize();
	void Draw(Rectangle);
};

NewMetaImpl0(PreviewPageItem, PictureItem);

Metric PreviewPageItem::GetMinSize()
{
	return (gPrintManager->GetPaperSize()+30)*4/4;
}

void PreviewPageItem::Draw(Rectangle)
{
	if (pic) {
		GrState st;
		st.Use();
		GrScale(4.0/4.0, 4.0/4.0);
		GrTranslate(15);
		
		Rectangle rr(gPrintManager->GetPaperSize());
		DrawShadow(rr, gPoint6, gInkWhite, gInkBlack);

		GrSetPenNormal();
		GrSetPenInk(ePatGrey50);
		GrStrokeRect(gPrintManager->GetViewRect());
		GrStrokeRect(gPrintManager->GetPrintRect());
		GrSetPenNormal();

		GrShowPicture(pic->BBox(), pic);
	}
}

//---- PreviewDialog -----------------------------------------------------------

const int
	cIdStop   = cIdFirstUser + 100,
	cIdNext   = cIdFirstUser + 101;

class PreviewDialog : public Dialog {
public:
	bool next, stop;
	TextItem *ti;
	PictureItem *pi;
public:
	PreviewDialog() : Dialog("Print Preview", eWinDefault)
		{ }
	VObject *DoMakeContent();
	void Control(int id, int part, void *val);
	void Show();
	void SetPicture(Picture *pict);
	void SetStatus(const char *msg)
		{ if (ti) ti->SetString(msg, TRUE); }
	Point GetInitialWindowSize()
		{ return gPrintManager->GetPaperSize()+80; }
};

void PreviewDialog::Show()
{
	next= stop= FALSE;
	ShowAt(gWindow, gWindow->contentRect.Center(), FALSE);
}

void PreviewDialog::SetPicture(Picture *pict)
{
	next= stop= FALSE;
	if (pict)
		pi->SetPicture(pict, TRUE);
}

VObject *PreviewDialog::DoMakeContent()
{
	pi= new PreviewPageItem;

	Scroller *scr= new Scroller(pi);
	scr->SetBgInk(ePatGrey50);
		
	VObject *v=
		new HBox(gPoint10, (VObjAlign)(eVObjVBase+eVObjHExpand),
			new ActionButton(cIdNext, "Next", TRUE),
			new ActionButton(cIdStop, "Stop"),
			new TextItem("State:"),
			ti= new TextItem("Page 9999 of 9999"),
			0
		);
	v->SetFlag(eVObjHFixed|eVObjVFixed);

	return
		new VExpander(gPoint2,
			new Matte(gPoint4, v),
			scr,
			0
		);
}

void ExitLoop()
{
	if (WindowSystem::grabport)
		WindowSystem::grabport->ExitLoop();
}

void PreviewDialog::Control(int id, int part, void *val)
{
	switch (id) {
	case cIdStop:
		stop= TRUE;
		ExitLoop();
		break;
	case cIdNext:
		next= TRUE;
		ExitLoop();
		break;
	default:
		Dialog::Control(id, part, val);
		break;
	}
}

//---- Preview -----------------------------------------------------------------

class Preview : public Printer {
	PreviewDialog *previewDialog;
	PictPort *pictPort;
	int pagecnt;
public:
	MetaDef(Preview);
	Preview()
		{ }
	~Preview()
		{ SafeDelete(previewDialog); }
	const char *GetName()
		{ return "Preview"; }
	bool CanPrint()
		{ return TRUE; }
	PrintPort *MakePrintPort(const char*)
		{ return pictPort= new PictPort(new Picture); }
	void Start(int pagecnt);
	bool OpenPage(int pageno, Rectangle pgr);
	bool ClosePage();
	void Finish();
	PrinterSettings *GetSettings()
		{ return gPrintManager->currSettings; }
};

NewMetaImpl0(Preview, Printer);

void Preview::Start(int pc)
{
	pagecnt= pc;
	previewDialog= new PreviewDialog;
	previewDialog->Show();
}

bool Preview::OpenPage(int pageno, Rectangle)
{
	previewDialog->SetStatus(form("Page %d of %d", pageno, pagecnt));
	return FALSE;
}

bool Preview::ClosePage()
{
	previewDialog->SetPicture(pictPort->GetPicture());
	((WindowPort*) previewDialog->GetWindow()->GetPortDesc())->GrabLoop();
	return previewDialog->stop;
}

void Preview::Finish()
{
	previewDialog->Close();
}

